package com.example.ws.web;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.example.ws.model.ChatHistory;
import com.example.ws.service.IChatHistoryService;
import com.example.ws.service.IMessageRankService;
import com.example.ws.service.IOnlineUserService;
import com.example.ws.service.RedisMessagePublisher;
import com.example.ws.util.SpringContextHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

@Component
@ServerEndpoint("/chat/{username}")
public class ChatEndpoint {

    private static IOnlineUserService onlineUserService;
    private static IMessageRankService IMessageRankService;
    private static RedisMessagePublisher redisMessagePublisher;

    @Autowired
    public void setService(IOnlineUserService ous, IMessageRankService mrs,RedisMessagePublisher rps) {
        onlineUserService = ous;
        IMessageRankService = mrs;
        redisMessagePublisher = rps;
    }

    private Session session;
    private String username;
    private static final ConcurrentMap<String, ChatEndpoint> chatEndpoints = new ConcurrentHashMap<>();

    @OnOpen
    public void onOpen(@PathParam("username") String username, Session session) {
        this.session = session;
        this.username = username;
        chatEndpoints.put(username, this);
        onlineUserService.userLogin(username);
        onlineUserService.storeSession(username,session);
        sendOnlineUsersUpdate();
        System.out.println("有新连接加入！名字：" + username);
    }

    @OnMessage
    public void onMessage(String message, Session session) throws IOException {
        System.out.println("客户端信息：" + message);
        if ("在线用户列表".equals(message) && session.isOpen()) {
            redisMessagePublisher.publishMessage(message);
            sendOnlineUsersUpdate();
        } else {
            try {
                JSONObject jsonObject = JSONUtil.parseObj(message);
                String targetUsername = jsonObject.getStr("targetUser");
                String actualMessage = jsonObject.getStr("content");

                // 先检查目标用户是否在线
                if (isUserOnline(targetUsername)) {
                    // 只有目标用户在线时才转发消息并保存记录
                    forwardMessage(targetUsername, actualMessage);
                    saveChatHistory(username, targetUsername, actualMessage);
                    updateMessageRank(username);
                } else {
                    sendSystemMessage("用户 " + targetUsername + " 不在线，消息未发送", session);
                }
            } catch (Exception e) {
                sendSystemMessage("消息格式错误，请使用 JSON 格式", session);
            }
        }
    }

    // 新增方法：检查用户是否在线
    private boolean isUserOnline(String username) {
        ChatEndpoint endpoint = chatEndpoints.get(username);
        return endpoint != null && endpoint.session != null && endpoint.session.isOpen();
    }

    @OnClose
    public void onClose(Session session) {
        try {
            // 先移除用户再广播更新
            chatEndpoints.remove(username);
            onlineUserService.userLogout(username);

            // 只在session还open时发送更新
            if(session.isOpen()) {
                sendOnlineUsersUpdate();
            }

            System.out.println("用户断开连接: " + username);
        } catch (Exception e) {
            System.err.println("关闭连接时出错: " + e.getMessage());
        }
    }

    @OnError
    public void onError(Session session, Throwable throwable) {
        System.err.println("Error: " + throwable.getMessage());
    }

    private void sendOnlineUsersUpdate(){
        if (!session.isOpen()) {
            return;
        }

        Set<String> users = onlineUserService.getOnlineUsers();
        String onlineUsersMessage = "在线用户列表:" + String.join(",", users);

        try {
            session.getBasicRemote().sendText(onlineUsersMessage);
        } catch (IOException e) {
            System.err.println("发送在线用户列表失败: " + e.getMessage());
        }
    }

    private void forwardMessage(String targetUsername, String message) throws IOException {
        ChatEndpoint targetEndpoint = chatEndpoints.get(targetUsername);
        if (targetEndpoint != null && targetEndpoint.session.isOpen()) {
            try {
                targetEndpoint.session.getBasicRemote()
                        .sendText(username + ":" + message);
            } catch (IOException e) {
                System.err.println("转发消息失败: " + e.getMessage());
            }
        } else {
            try {
                if (session.isOpen()) {
                    sendSystemMessage("用户 " + targetUsername + " 不在线", session);
                }
            } catch (IOException e) {
                System.err.println("发送系统消息失败: " + e.getMessage());
            }
        }
    }

    private void saveChatHistory(String fromUser, String toUser, String content) {
        ChatHistory chatHistory = new ChatHistory();
        chatHistory.setContent(content);
        chatHistory.setFromUser(fromUser);
        chatHistory.setToUser(toUser);
        getHistoryService().add(chatHistory);
    }

    private void updateMessageRank(String username) {
        IMessageRankService.incrementMessageCount(username);
    }

    private void sendSystemMessage(String message, Session session) throws IOException {
        session.getBasicRemote().sendText(message);
    }

    private IChatHistoryService getHistoryService() {
        return SpringContextHolder.getBean(IChatHistoryService.class);
    }
}